home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / GLX / cutNpaste / Xclipboard / xclipboard.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  11.1 KB  |  473 lines

  1. /*
  2.  * $XConsortium: xclipboard.c,v 1.15 89/12/15 20:11:09 keith Exp $
  3.  *
  4.  * Copyright 1989 Massachusetts Institute of Technology
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software and its
  7.  * documentation for any purpose and without fee is hereby granted, provided
  8.  * that the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation, and that the name of M.I.T. not be used in advertising
  11.  * or publicity pertaining to distribution of the software without specific,
  12.  * written prior permission.  M.I.T. makes no representations about the
  13.  * suitability of this software for any purpose.  It is provided "as is"
  14.  * without express or implied warranty.
  15.  *
  16.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  17.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  18.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  20.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
  21.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  *
  23.  * Author:  Ralph Swick, DEC/Project Athena
  24.  * Updated for R4:  Chris D. Peterson,  MIT X Consortium.
  25.  * Reauthored by: Keith Packard, MIT X Consortium.
  26.  */
  27.  
  28. /* $XConsortium: xclipboard.c,v 1.15 89/12/15 20:11:09 keith Exp $ */
  29.  
  30. #include <stdio.h>
  31. #include <X11/Intrinsic.h>
  32. #include <X11/StringDefs.h>
  33. #include <X11/Xatom.h>
  34.  
  35. #include <X11/Xmu/Atoms.h>
  36. #include <X11/Xmu/StdSel.h>
  37.  
  38. #include <X11/Xaw/Form.h>
  39. #include <X11/Xaw/Command.h>
  40. #include <X11/Xaw/AsciiText.h>
  41. #include <X11/Xaw/Cardinals.h>
  42.  
  43. #define Command commandWidgetClass
  44. #define Text    asciiTextWidgetClass
  45.  
  46. #define INFINITY 10000000    /* pretty big, huh? */
  47.  
  48. typedef struct _Clip {
  49.     struct _Clip    *next, *prev;
  50.     char        *clip;
  51.     int            avail;
  52. } ClipRec, *ClipPtr;
  53.  
  54. extern char *malloc ();
  55.  
  56. static long TextLength (w)
  57.     Widget  w;
  58. {
  59.     return XawTextSourceScan (XawTextGetSource (w),
  60.                   (XawTextPosition) 0,
  61.                    XawstAll, XawsdRight, 1, TRUE);
  62. }
  63.  
  64. SaveClip (w, clip)
  65.     Widget  w;
  66.     ClipPtr clip;
  67. {
  68.     Arg        args[1];
  69.     char    *data;
  70.     int        len;
  71.     Widget  source;
  72.  
  73.     source = XawTextGetSource (w);
  74.     XtSetArg (args[0], XtNstring, &data);
  75.     XtGetValues (source, args, 1);
  76.     len = strlen (data);
  77.     if (len >= clip->avail)
  78.     {
  79.     if (clip->clip)
  80.         free (clip->clip);
  81.     clip->clip = malloc (len + 1);
  82.     if (!clip->clip)
  83.         clip->avail = 0;
  84.     else
  85.         clip->avail = len + 1;
  86.     }
  87.     if (clip->avail)
  88.     {
  89.     strcpy (clip->clip, data);
  90.     }
  91. }
  92.  
  93. RestoreClip (w, clip)
  94.     Widget  w;
  95.     ClipPtr clip;
  96. {
  97.     Arg        args[1];
  98.     Widget  source;
  99.  
  100.     source = XawTextGetSource (w);
  101.     XtSetArg (args[0], XtNstring, clip->clip);
  102.     XtSetValues (source, args, 1);
  103. }
  104.  
  105. ClipPtr
  106. NewClip (w, old)
  107.     Widget  w;
  108.     ClipPtr old;
  109. {
  110.     ClipPtr newClip;
  111.  
  112.     newClip = (ClipPtr) malloc (sizeof (ClipRec));
  113.     if (!newClip)
  114.     return newClip;
  115.     newClip->clip = 0;
  116.     newClip->avail = 0;
  117.     newClip->prev = old;
  118.     newClip->next = NULL;
  119.     if (old)
  120.     {
  121.     newClip->next = old->next;
  122.     old->next = newClip;
  123.     }
  124.     return newClip;
  125. }
  126.  
  127. DeleteClip (w, clip)
  128.     Widget  w;
  129.     ClipPtr clip;
  130. {
  131.     if (clip->prev)
  132.     clip->prev->next = clip->next;
  133.     if (clip->next)
  134.     clip->next->prev = clip->prev;
  135.     if (clip->clip)
  136.     free (clip->clip);
  137.     free ((char *) clip);
  138. }
  139.  
  140. static ClipPtr    currentClip;
  141. static Widget    text, nextButton, prevButton;
  142.  
  143. static void set_button_state ()
  144. {
  145.     Boolean prevvalid, nextvalid;
  146.     Arg arg;
  147.  
  148.     prevvalid = False;
  149.     nextvalid = False;
  150.     if (currentClip)
  151.     {
  152.     prevvalid = currentClip->prev != NULL;
  153.     nextvalid = currentClip->next != NULL;
  154.     }
  155.     arg.name = XtNsensitive;
  156.     arg.value = (XtArgVal) prevvalid;
  157.     XtSetValues (prevButton, &arg, ONE);
  158.     arg.value = (XtArgVal) nextvalid;
  159.     XtSetValues (nextButton, &arg, ONE);
  160. }
  161.  
  162. static void
  163. NextCurrentClip ()
  164. {
  165.     if (currentClip && currentClip->next)
  166.     {
  167.     SaveClip (text, currentClip);
  168.     currentClip = currentClip->next;
  169.     RestoreClip (text, currentClip);
  170.     set_button_state ();
  171.     }
  172. }
  173.  
  174. static void
  175. PrevCurrentClip ()
  176. {
  177.     if (currentClip && currentClip->prev)
  178.     {
  179.     SaveClip (text, currentClip);
  180.     currentClip = currentClip->prev;
  181.     RestoreClip (text, currentClip);
  182.     set_button_state ();
  183.     }
  184. }
  185.  
  186. static void
  187. DeleteCurrentClip ()
  188. {
  189.     ClipPtr newCurrent;
  190.     if (currentClip)
  191.     {
  192.     if (currentClip->prev)
  193.     {
  194.         newCurrent = currentClip->prev;
  195.     }
  196.     else
  197.     {
  198.         newCurrent = currentClip->next;
  199.     }
  200.     DeleteClip (text, currentClip);
  201.     currentClip = newCurrent;
  202.     if (currentClip)
  203.         RestoreClip (text, currentClip);
  204.     else
  205.     {
  206.         EraseTextWidget ();
  207.     }
  208.     set_button_state ();
  209.     }
  210. }
  211.  
  212. static void
  213. Quit ()
  214. {
  215.     XtCloseDisplay  (XtDisplay (text));
  216.     exit (0);
  217. }
  218.  
  219. static void
  220. NewCurrentClip ()
  221. {
  222.     NewCurrentClipContents ("", 0);
  223. }
  224.  
  225. NewCurrentClipContents (data, len)
  226.     char    *data;
  227.     int        len;
  228. {
  229.     XawTextBlock textBlock;
  230.     ClipPtr newCurrent;
  231.  
  232.     if (!currentClip && TextLength (text))
  233.     currentClip = NewClip (text, (ClipPtr) 0);
  234.     if (currentClip)
  235.     SaveClip (text, currentClip);
  236.     /* append new clips at the end */
  237.     while (currentClip && currentClip->next)
  238.     currentClip = currentClip->next;
  239.     newCurrent = NewClip (text, currentClip);
  240.     
  241.     currentClip = newCurrent;
  242.  
  243.     textBlock.ptr = data;
  244.     textBlock.firstPos = 0;
  245.     textBlock.length = len;
  246.     textBlock.format = FMT8BIT;
  247.     if (XawTextReplace(text, 0, TextLength (text), &textBlock))
  248.     XBell( XtDisplay(text), 0);
  249.     set_button_state ();
  250. }
  251.  
  252. EraseTextWidget ()
  253. {
  254.     XawTextBlock block;
  255.  
  256.     block.ptr = "";
  257.     block.length = 0;
  258.     block.firstPos = 0;
  259.     block.format = FMT8BIT;
  260.  
  261.     XawTextReplace(text, 0, INFINITY, &block);
  262.     /* If this fails, too bad. */
  263. }
  264.  
  265.  
  266. XtActionsRec xclipboard_actions[] = {
  267.     "NewClip", NewCurrentClip,
  268.     "NextClip",    NextCurrentClip,
  269.     "PrevClip", PrevCurrentClip,
  270.     "DeleteClip", DeleteCurrentClip,
  271.     "Quit", Quit,
  272. };
  273.  
  274. static XrmOptionDescRec table[] = {
  275.     {"-w",        "*text*wrap",        XrmoptionNoArg,  "Word"},
  276.     {"-nw",        "*text*wrap",        XrmoptionNoArg,  "Never"},
  277. };
  278.  
  279. static void    LoseSelection ();
  280. static void    InsertClipboard ();
  281. static Boolean    ConvertSelection();
  282.  
  283. static void 
  284. InsertClipboard(w, client_data, selection, type, value, length, format)
  285. Widget w;
  286. caddr_t client_data;
  287. Atom *selection, *type;
  288. caddr_t value;
  289. unsigned long *length;
  290. int *format;
  291. {
  292.     if (*type == 0 /*XT_CONVERT_FAIL*/ || *length == 0) {
  293. #ifdef EBUG
  294.     fprintf(stderr,"Convert failed - no reassertion *type %d *length %d\n", 
  295.          *type, *length);
  296. #endif
  297.     XBell( XtDisplay(w), 0 );
  298.     return;
  299.     }
  300.     
  301.     NewCurrentClipContents ((char *) value, *length);
  302.  
  303. #ifdef EBUG
  304.     fprintf(stderr,"Asserting Ownership of Clipboard Selection\n");
  305. #endif
  306.     XtOwnSelection(w, XA_CLIPBOARD(XtDisplay(w)), CurrentTime,
  307.            ConvertSelection, LoseSelection, NULL);
  308.  
  309.     XtFree(value);
  310. }
  311.  
  312. static Boolean ConvertSelection(w, selection, target,
  313.                 type, value, length, format)
  314.     Widget w;
  315.     Atom *selection, *target, *type;
  316.     caddr_t *value;
  317.     unsigned long *length;
  318.     int *format;
  319. {
  320.     Display* d = XtDisplay(w);
  321.     XSelectionRequestEvent* req =
  322.     XtGetSelectionRequest(w, *selection, (XtRequestId)NULL);
  323.  
  324.     if (*target == XA_TARGETS(d)) {
  325.     Atom* targetP;
  326.     Atom* std_targets;
  327.     unsigned long std_length;
  328.     XmuConvertStandardSelection(w, req->time, selection, target, type,
  329.                   (caddr_t*)&std_targets, &std_length, format);
  330.     *value = XtMalloc(sizeof(Atom)*(std_length + 5));
  331.     targetP = *(Atom**)value;
  332.     *targetP++ = XA_STRING;
  333.     *targetP++ = XA_TEXT(d);
  334.     *targetP++ = XA_LENGTH(d);
  335.     *targetP++ = XA_LIST_LENGTH(d);
  336.     *targetP++ = XA_CHARACTER_POSITION(d);
  337.     *length = std_length + (targetP - (*(Atom **) value));
  338.     bcopy((char*)std_targets, (char*)targetP, sizeof(Atom)*std_length);
  339.     XtFree((char*)std_targets);
  340.     *type = XA_ATOM;
  341.     *format = 32;
  342.     return True;
  343.     }
  344.  
  345.     if (*target == XA_LIST_LENGTH(d) ||
  346.     *target == XA_LENGTH(d))
  347.     {
  348.         long * temp;
  349.         
  350.         temp = (long *) XtMalloc(sizeof(long));
  351.         if (*target == XA_LIST_LENGTH(d))
  352.             *temp = 1L;
  353.         else            /* *target == XA_LENGTH(d) */
  354.             *temp = (long) TextLength (w);
  355.         
  356.         *value = (caddr_t) temp;
  357.         *type = XA_INTEGER;
  358.         *length = 1L;
  359.         *format = 32;
  360.         return True;
  361.     }
  362.     
  363.     if (*target == XA_CHARACTER_POSITION(d))
  364.     {
  365.         long * temp;
  366.         
  367.         temp = (long *) XtMalloc(2 * sizeof(long));
  368.         temp[0] = (long) 0;
  369.         temp[1] = TextLength (w);
  370.         *value = (caddr_t) temp;
  371.         *type = XA_SPAN(d);
  372.         *length = 2L;
  373.         *format = 32;
  374.         return True;
  375.     }
  376.     
  377.     if (*target == XA_STRING ||
  378.       *target == XA_TEXT(d) ||
  379.       *target == XA_COMPOUND_TEXT(d))
  380.     {
  381.     extern char *_XawTextGetSTRING();
  382.         if (*target == XA_COMPOUND_TEXT(d))
  383.         *type = *target;
  384.         else
  385.         *type = XA_STRING;
  386.     *length = TextLength (w);
  387.         *value = _XawTextGetSTRING((TextWidget) w, 0, *length);
  388.         *format = 8;
  389.         return True;
  390.     }
  391.     
  392.     if (XmuConvertStandardSelection(w, req->time, selection, target, type,
  393.                     value, length, format))
  394.     return True;
  395.  
  396.     return False;
  397. }
  398.  
  399. static void LoseSelection(w, selection)
  400.     Widget w;
  401.     Atom *selection;
  402. {
  403. #ifdef EBUG
  404.     fprintf(stderr,"Losing Clipboard Selection so get info for Clipboard\n");
  405. #endif
  406.     XtGetSelectionValue(w, *selection, XA_STRING, InsertClipboard,
  407.             NULL, CurrentTime);
  408. }
  409.  
  410. /*ARGSUSED*/
  411. static Boolean RefuseSelection(w, selection, target,
  412.                    type, value, length, format)
  413.     Widget w;
  414.     Atom *selection, *target, *type;
  415.     caddr_t *value;
  416.     unsigned long *length;
  417.     int *format;
  418. {
  419.     return False;
  420. }
  421.  
  422. /*ARGSUSED*/
  423. static void LoseManager(w, selection)
  424.     Widget w;
  425.     Atom *selection;
  426. {
  427.     XtError("another clipboard has taken over control\n");
  428. }
  429.  
  430. void
  431. main(argc, argv)
  432. int argc;
  433. char **argv;
  434. {
  435.     Arg args[2];
  436.     Widget top, parent, quit, delete, new;
  437.     Atom manager;
  438.  
  439.     top = XtInitialize( "xclipboard", "XClipboard", table, XtNumber(table),
  440.               &argc, argv);
  441.  
  442.     XtAddActions (xclipboard_actions, XtNumber (xclipboard_actions));
  443.     /* CLIPBOARD_MANAGER is a non-standard mechanism */
  444.     manager = XInternAtom(XtDisplay(top), "CLIPBOARD_MANAGER", False);
  445.     if (XGetSelectionOwner(XtDisplay(top), manager))
  446.     XtError("another clipboard is already running\n");
  447.  
  448.     parent = XtCreateManagedWidget("form", formWidgetClass, top, NULL, ZERO);
  449.     quit = XtCreateManagedWidget("quit", Command, parent, NULL, ZERO);
  450.     delete = XtCreateManagedWidget("delete", Command, parent, NULL, ZERO);
  451.     new = XtCreateManagedWidget("new", Command, parent, NULL, ZERO);
  452.     nextButton = XtCreateManagedWidget("next", Command, parent, NULL, ZERO);
  453.     prevButton = XtCreateManagedWidget("prev", Command, parent, NULL, ZERO);
  454.  
  455.     XtSetArg(args[0], XtNtype, XawAsciiString);
  456.     XtSetArg(args[1], XtNeditType, XawtextEdit);
  457.     text = XtCreateManagedWidget( "text", Text, parent, args, TWO);
  458.  
  459.     set_button_state ();
  460.  
  461.     XtRealizeWidget(top);
  462.  
  463. #ifdef EBUG
  464.     fprintf(stderr,"Asserting ownership of XA_CLIPBOARD\n");
  465. #endif
  466.     XtOwnSelection(text, manager, CurrentTime,
  467.            RefuseSelection, LoseManager, NULL);
  468.     XtOwnSelection(text, XA_CLIPBOARD(XtDisplay(text)), CurrentTime,
  469.            ConvertSelection, LoseSelection, NULL);
  470.  
  471.     XtMainLoop();
  472. }
  473.